package com.apobates.forum.trident.controller.admin;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.apobates.forum.trident.exception.ResourceNotFoundException;
import com.apobates.forum.trident.controller.form.TopicConfigForm;
import com.apobates.forum.trident.controller.form.TopicModifyForm;
import com.apobates.forum.trident.controller.form.TopicPublishForm;
import com.apobates.forum.core.api.ImageIOMeta;
import com.apobates.forum.core.api.service.BoardService;
import com.apobates.forum.core.api.service.PostsService;
import com.apobates.forum.core.api.service.SmileyThemeService;
import com.apobates.forum.core.api.service.TopicCategoryService;
import com.apobates.forum.core.api.service.TopicConfigService;
import com.apobates.forum.core.api.service.TopicService;
import com.apobates.forum.core.api.service.TopicTagService;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.Posts;
import com.apobates.forum.core.entity.SmileyTheme;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicCategory;
import com.apobates.forum.core.entity.TopicConfig;
import com.apobates.forum.core.entity.TopicTag;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.member.entity.MemberGroupEnum;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.utils.CommonBean;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.FrontPageURL;
import com.apobates.forum.utils.TipMessage;
import com.apobates.forum.utils.lang.EnumArchitecture;
import com.apobates.forum.utils.persistence.Page;
import com.apobates.forum.utils.persistence.PageRequest;
import com.apobates.forum.utils.persistence.Pageable;
/**
 * 话题控制器
 * 
 * @author xiaofanku
 * @since 20190407
 */
@Controller
@RequestMapping(value = "/admin/topic")
public class AdminTopicController {
	@Autowired
	private TopicService topicService;
	@Autowired
	private TopicTagService topicTagService;
	@Autowired
	private TopicCategoryService topicCategoryService;
	@Autowired
	private PostsService postsService;
	@Autowired
	private TopicConfigService topicConfigService;
	@Autowired
	private BoardService boardService;
	@Autowired
	private SmileyThemeService smileyThemeService;
	@Autowired
	private ImageIOMeta imageIOConfig;
	@Value("${site.pageSize}")
	private int pageSize;
	
	@GetMapping(path="/")
	public String listPage(
			@RequestParam(name="board", required=false, defaultValue="0") long boardId,
			HttpServletRequest request, 
			Model model) {
		Stream<Topic> rs = (boardId>0)?topicService.getRecentForBoard(boardId, pageSize):topicService.getRecentIgnoreCondition(pageSize);
		model.addAttribute("rs", rs.collect(Collectors.toList()));
		return "admin/topic/index";
	}
	
	@GetMapping(path="/edit")
	public String editForm(
			@RequestParam("id")long id, 
			HttpServletRequest request, 
			Model model) {
		Topic topicObj = topicService.get(id).orElseThrow(()->new ResourceNotFoundException("话题不存在或暂时无法访问"));
		//禁止编辑的
		if(TopicCategory.isForbidCategoryValue().contains(topicObj.getTopicCategoryValue())){
			throw new ResourceNotFoundException("话题所在的分类禁止二次编辑");
		}
		Posts content = postsService.getPostsContentForEditByTopic(id, imageIOConfig).orElseThrow(()->new ResourceNotFoundException("内容不存在或暂时无法访问"));
		String words = topicTagService.getAllBy(id).stream().map(TopicTag::getNames).collect(Collectors.joining(","));
		//
		TopicModifyForm form = new TopicModifyForm();
		form.setTitle(topicObj.getTitle());
		form.setWords(words);
		form.setRecord(id);
		form.setContent(content.getContent());
		//
		form.setToken(Commons.randomAlphaNumeric(8));
		model.addAttribute("form", form);
		model.addAttribute("smileyThemes", getSmileyTheme());
		return "admin/topic/edit";
	}
	@PostMapping(path="/edit")
	public String editAction(
			@ModelAttribute("form")TopicModifyForm form, 
			MemberSessionBean mbean,
			HttpServletRequest request, 
			Model model) {
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, form.getToken());
		String errMsg=null;boolean symbol=false;
		try{
			symbol = topicService.edit(
				form.getLongRecord(), 
				form.getTitle(), 
				form.getContent(), 
				form.getWordsArray(), 
				imageIOConfig, 
				aec).orElse(false);
		}catch(IllegalStateException e){
			errMsg=e.getMessage();
		}
		if(symbol){
			return "redirect:/admin/topic/"+form.getLongRecord()+".xhtml";
		}
		form.setToken(Commons.randomAlphaNumeric(8));
		model.addAttribute("form", form);
		model.addAttribute("smileyThemes", getSmileyTheme());
		//
		model.addAttribute("errors", Commons.optional(errMsg, "编辑话题操作失败"));
		return "admin/topic/edit";
	}
	//新话题
	@GetMapping(path="/publish")
	public String createTopicForm(
			@RequestParam(name="volumes", required=false, defaultValue="-1") int volumesId,
			@RequestParam(name="board", required=false, defaultValue="0") long boardId,
			HttpServletRequest request, 
			Model model){
		TopicPublishForm form = new TopicPublishForm();
		form.setBoard(boardId+"");
		form.setVolumes(volumesId+"");
		//
		form.setToken(Commons.randomAlphaNumeric(8));
		model.addAttribute("form", form);
		model.addAttribute("smileyThemes", getSmileyTheme());
		return "admin/topic/create";
	}
	@PostMapping(path="/publish")
	public String createTopicAction(
			@ModelAttribute("form")TopicPublishForm form, 
			MemberSessionBean mbean,
			HttpServletRequest request, 
			Model model){
		int volumesId=form.getIntegerVolumes();
		long boardId=form.getLongBoard();
		TopicCategory tc=topicCategoryService.get(form.getCategory()).orElse(TopicCategory.empty());
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, form.getToken());
		//
		String errMsg=null;
		if(boardId>0 && volumesId>=0) { //有可能在默认分组中
			try{
				long data = topicService.create(
						volumesId, 
						boardId, 
						tc.getNames(), tc.getValue(), 
						form.getTitle(), 
						form.getContent(), 
						form.getWordsArray(), 
						imageIOConfig, 
						aec);
				if(data>0) {
					return "redirect:/admin/topic/"+data+".xhtml";
				}
			}catch(IllegalStateException e){
				errMsg=e.getMessage();
			}
		}
		form.setToken(Commons.randomAlphaNumeric(8));
		model.addAttribute("form", form);
		model.addAttribute("smileyThemes", getSmileyTheme());
		//
		model.addAttribute("errors", Commons.optional(errMsg, "发布话题操作失败"));
		return "admin/topic/create";
	}
	
	@GetMapping(path="/config")
	public String topicConfigForm(
			@RequestParam("id")long topicId,
			HttpServletRequest request, 
			Model model) {
		TopicConfig c = topicConfigService.getByTopicId(topicId).orElse(TopicConfig.empty());
		TopicConfigForm form = new TopicConfigForm();
		//
		form.setPrivacy(c.isPrivacy());
		form.setReply(c.isReply());
		form.setNotify(c.isNotify());
		form.setAtomPoster(c.isAtomPoster());
		form.setWriteMinInterrupt(c.getWriteMinInterrupt()+"");
		//r
		form.setReadMinScore(c.getReadMinScore()+"");
		form.setReadLowMemberGroup(c.getReadLowMemberGroup().getSymbol()+"");
		form.setReadLowMemberRole(c.getReadLowMemberRole().getSymbol()+"");
		form.setReadLowMemberLevel(c.getReadLowMemberLevel()+"");
		//w
		form.setWriteMinScore(c.getWriteMinScore()+"");
		form.setWriteLowMemberGroup(c.getWriteLowMemberGroup().getSymbol()+"");
		form.setWriteLowMemberRole(c.getWriteLowMemberRole().getSymbol()+"");
		form.setWriteLowMemberLevel(c.getWriteLowMemberLevel()+"");
		//
		form.setRecord(c.getId());
		form.setTopicId(c.getTopicId()+"");
		//
		form.setToken(Commons.randomAlphaNumeric(8));
		model.addAttribute("form", form);
		//
		model.addAttribute("memberGroupData", EnumArchitecture.getInstance(MemberGroupEnum.class));
		model.addAttribute("memberRoleData", EnumArchitecture.getInstance(MemberRoleEnum.class));
		return "admin/topic/config";
	}
	@PostMapping(path="/config")
	public String topicConfigAction(
			@ModelAttribute("form")TopicConfigForm form, 
			MemberSessionBean mbean, 
			HttpServletRequest request, 
			Model model) {
		long topicId = form.getLongTopicId();
		if(topicId == 0){
			form.setToken(Commons.randomAlphaNumeric(8));
			model.addAttribute("form", form);
			//
			model.addAttribute("memberGroupData", EnumArchitecture.getInstance(MemberGroupEnum.class));
			model.addAttribute("memberRoleData", EnumArchitecture.getInstance(MemberRoleEnum.class));
			//
			model.addAttribute("errors", "话题参数丢失");
			return "admin/topic/config";
		}
		TopicConfig config = new TopicConfig();
		config.setId(form.getLongRecord());
		config.setTopicId(topicId);
		config.setPrivacy(form.getBooleanPrivacy());
		config.setReply(form.getBooleanReply());
		config.setNotify(form.getBooleanNotify());
		config.setAtomPoster(form.getBooleanAtomPoster());
		config.setWriteMinInterrupt(form.getIntegerWriteMinInterrupt());
		//r
		config.setReadMinScore(form.getIntegerReadMinScore());
		MemberGroupEnum rmg = (MemberGroupEnum)EnumArchitecture.getInstance(form.getIntegerReadLowMemberGroup(), MemberGroupEnum.class).orElse((EnumArchitecture)MemberGroupEnum.GUEST);
		config.setReadLowMemberGroup(rmg);
		MemberRoleEnum rmr = (MemberRoleEnum)EnumArchitecture.getInstance(form.getIntegerReadLowMemberRole(), MemberRoleEnum.class).orElse((EnumArchitecture)MemberRoleEnum.NO);
		config.setReadLowMemberRole(rmr);
		config.setReadLowMemberLevel(form.getIntegerReadLowMemberLevel());
		//w
		config.setWriteMinScore(form.getIntegerWriteMinScore());
		MemberGroupEnum wmg = (MemberGroupEnum)EnumArchitecture.getInstance(form.getIntegerWriteLowMemberGroup(), MemberGroupEnum.class).orElse((EnumArchitecture)MemberGroupEnum.CARD);
		config.setWriteLowMemberGroup(wmg);
		MemberRoleEnum wmr = (MemberRoleEnum)EnumArchitecture.getInstance(form.getIntegerWriteLowMemberRole(), MemberRoleEnum.class).orElse((EnumArchitecture)MemberRoleEnum.NO);
		config.setWriteLowMemberRole(wmr);
		config.setWriteLowMemberLevel(form.getIntegerWriteLowMemberLevel());
		//editTopicConfig(long id, TopicConfig updateConfig, long configId, ActionEventCulpritor culpritor) {
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, form.getToken());
		String errMsg=null;
		try{
			Optional<Boolean> symbol = topicService.editTopicConfig(
				form.getLongTopicId(), 
				config, 
				form.getLongRecord(), 
				aec);
			if(symbol.isPresent()) {
				return "redirect:/admin/topic/"+config.getTopicId()+".xhtml";
			}
		}catch(IllegalStateException e){
			errMsg=e.getMessage();
		}
		form.setToken(Commons.randomAlphaNumeric(8));
		model.addAttribute("form", form);
		//
		model.addAttribute("memberGroupData", EnumArchitecture.getInstance(MemberGroupEnum.class));
		model.addAttribute("memberRoleData", EnumArchitecture.getInstance(MemberRoleEnum.class));
		model.addAttribute("errors", Commons.optional(errMsg, "更新话题的配置文件失败"));
		return "admin/topic/config";
	}
	//版块下的话题
	@GetMapping(path="/list/{id}.xhtml")
	public String topicHome(
			@PathVariable("id") long boardId,
			@RequestParam(value = "p", required = false, defaultValue = "1") int page,
			HttpServletRequest request,
			Model model) {
		Board board = boardService.get(boardId).orElseThrow(()->new ResourceNotFoundException("版块不存在或暂时无法访问"));
		FrontPageURL fpbuild = new FrontPageURL(request.getContextPath() + "/admin/topic/list/"+boardId+".xhtml").addPageSize("number", pageSize);
		Pageable pr = new PageRequest(page, fpbuild.getPageSize());
		Page<Topic> rs = topicService.getAll(boardId, pr);
		model.addAttribute("rs", rs.getResult().collect(Collectors.toList()));
		model.addAttribute("pageData", pr.toData(fpbuild, rs.getTotalElements()));
		model.addAttribute("board", board);
		return "admin/topic/board";
	}
	/*话题统计
	@GetMapping(path="/stats")
	public String getTopicStats(
			@RequestParam("id")long topicId, 
			@RequestParam("volume")int boardGroupId, 
			@RequestParam("board")long boardId, 
			HttpServletRequest request, 
			Model model){
		TopicStats ts = topicStatsService.getByTopic(topicId).getOrElse(new TopicStats(topicId, boardGroupId, boardId));
		model.addAttribute("stats", ts);
		return "admin/topic/stats";
	}*/
	//锁定话题
	@PostMapping(path="/lock", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public TipMessage lockTopicAction(
			@RequestParam("id")long topicId,
			MemberSessionBean mbean,
			HttpServletRequest request, 
			Model model){
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, "");
		try{
			boolean symbol = topicService.lock(topicId, aec).orElse(false);
			if (symbol) {
				return TipMessage.ofSuccess("成功锁定话题");
			}
		}catch(IllegalStateException e){
			return TipMessage.ofError(e.getMessage());
		}
		return TipMessage.ofError("操作失败");
	}
	//锁定话题
	@PostMapping(path="/lock/remove", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public TipMessage removeLockTopicAction(
			@RequestParam("id")long topicId,
			MemberSessionBean mbean,
			HttpServletRequest request, 
			Model model){
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, "");
		try{
			boolean symbol = topicService.releaseLock(topicId, aec).orElse(false);
			if (symbol) {
				return TipMessage.ofSuccess("成功解锁话题");
			}
		}catch(IllegalStateException e){
			return TipMessage.ofError(e.getMessage());
		}
		return TipMessage.ofError("操作失败");
	}
	//删除话题
	@PostMapping(path="/remove", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public TipMessage removeTopicAction(
			@RequestParam("id")long topicId,
			MemberSessionBean mbean,
			HttpServletRequest request,
			Model model){
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, "");
		try{
			boolean symbol = topicService.remove(topicId, aec).orElse(false);
			if (symbol) {
				return TipMessage.ofSuccess("话题删除成功");
			}
		}catch(IllegalStateException e){
			return TipMessage.ofError(e.getMessage());
		}
		return TipMessage.ofError("操作失败");
	}
	//置顶话题
	@PostMapping(path="/top", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public TipMessage setTopTopicAction(
			@RequestParam("id")long topicId,
			MemberSessionBean mbean,
			HttpServletRequest request,
			Model model){
		ActionEventCulpritor aec = ActionEventCulpritor.getInstance(mbean.getMid(), mbean.getNickname(), request, "");
		try{
			boolean symbol = topicService.editTop(topicId, aec).orElse(false);
			if (symbol) {
				return TipMessage.ofSuccess("话题置顶成功");
			}
		}catch(IllegalStateException e){
			return TipMessage.ofError(e.getMessage());
		}
		return TipMessage.ofError("操作失败");
	}
	
	@GetMapping(path="/{id}.xhtml")
	public String topicViewPage(
			@PathVariable("id") long topicId,
			HttpServletRequest request, 
			Model model){
		Topic topic = topicService.getTopicContentAndStats(topicId, imageIOConfig);
		if (topic==null) {
			throw new ResourceNotFoundException("话题不存在或暂时无法访问");
		}
		//标签
		List<TopicTag> tags = topicTagService.getAllBy(topicId);
		topic.getTages().addAll(tags);
		
		model.addAttribute("topic", topic);
		return "admin/topic/view";
	}
	//加载话题的标题
	@GetMapping(path="/title", produces = "application/json;charset=UTF-8")
	@ResponseBody
	public CommonBean getTopicTitle(
			@RequestParam("id")long id, 
			HttpServletRequest request,
			Model model){
		if(id==0){
			return new CommonBean(0, "所有");
		}
		String title="话题";
		Optional<Topic> topic = topicService.get(id);
		if(topic.isPresent()){
			title = topic.get().getTitle();
		}
		return new CommonBean(id, title);
	}
	//Key=SmileyTheme.directNames, Value=SmileyTheme.title
	private Map<String,String> getSmileyTheme(){
		return smileyThemeService.getAll().collect(Collectors.toMap(SmileyTheme::getDirectNames, SmileyTheme::getTitle));
	}
}
